﻿using Fclp;
using RunAsThisUser.ToolSet;
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Security.Cryptography;

namespace RunAsThisUser
{
    class Program
    {

        private static string username = null;
        private static string password = null;
        private static string domain = null;
        private static bool generate = false;
        private static string encrypted = null;

        static void Main(string[] args)
        {
            var parser = new FluentCommandLineParser();
            parser.Setup<string>('u', "user")
                .Callback(u => username = u)
                .WithDescription("Username to encrypt");

            parser.Setup<string>('p', "password")
                .Callback(p => password = p)
                .WithDescription("Password to encrypt");


            parser.Setup<string>('d', "domain")
                .Callback(d => domain = d)
                .WithDescription("Domain to encrypt");


            parser.Setup<bool>('g', "generate")
                .Callback(g => generate = g)
                .WithDescription("Generates a new encryption key dll");

            parser.SetupHelp(new string[] { "h", "?", "help" })
           .UseForEmptyArgs()
           .Callback(s => Console.WriteLine(s));

            var result = parser.Parse(args);
            if (result.HasErrors)
            {
                Console.WriteLine(result.ErrorText);
                Environment.Exit(-1);
            }

            if (username != null && password != null && domain != null)
            {
                var plainText = String.Format("{0},{1},{2}", username, domain, password);
                var encryptedArray = Tools.EncryptStringToBytes(plainText, Tools.PrivateKey, Tools.IVKey);
                File.WriteAllBytes("credential.key", encryptedArray);
            }

            else if (generate)
            {
                var success = GenerateNewSecurityDLL();
                if (success)
                    Console.WriteLine("Generated new encryption dll");
                else
                    Console.WriteLine("Failed to generate new encryption dll");
            }
        }

        /// <summary>
        /// Generates dynamic dll file that contains the initialization vector and key for encryption and decryption.
        /// </summary>
        /// <returns></returns>
        private static bool GenerateNewSecurityDLL()
        {
            string output = "";
            using (var managed = new RijndaelManaged())
            {
                output += "public class DynGen {public static readonly byte[] ivKey = new byte[]{";
                managed.GenerateIV();
                foreach (var item in managed.IV)
                {
                    output += String.Format("{0},", item);
                }
                output = output.TrimEnd(new char[] { ',' });
                output += "};";

                output += "public static readonly byte[] privateKey = new byte[]{";
                managed.GenerateKey();
                foreach (var item in managed.Key)
                {
                    output += String.Format("{0},", item);
                }
                output = output.TrimEnd(new char[] { ',' });
                output += "};}";
            }

            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            parameters.OutputAssembly = "DynGen.dll";

            CompilerResults results =
                CodeDomProvider.CreateProvider("CSharp").CompileAssemblyFromSource(parameters, output);
            if (results.Errors.Count == 0) return true;
            return false;
        }

    }
}
